import editorStyle from "../util/defaultStyle";
import { GraphStyle } from "@/utils/styles";

import { SingleShapeMixin } from "@/g6/g6";
import { Item } from "@/g6/g6";

Item.prototype.anchorDebounceTimer = null;

Item.prototype.getShowAnchorPoints = function () {
  return [
    [0, -0.5],
    [-0.5, 0],
    [0, 0.5],
    [0.5, 0],
  ];
};

Item.prototype.showAnchor = function (graph) {
  if (!!this.anchorDebounceTimer) {
    clearTimeout(this.anchorDebounceTimer);
    this.anchorDebounceTimer = null;
  }
  if (this.getType() !== "node") {
    return;
  }
  const group = this.getContainer();
  if (!group.anchorShapes) {
    group.anchorShapes = [];
    group.keyShape = this;
    const bbox = this.getBBox();

    this.getShowAnchorPoints().forEach((point, index) => {
      const anchor = createAnchor(
        index,
        {
          x: bbox.width * point[0],
          y: bbox.height * point[1],
        },
        group
      );
      group.anchorShapes.push(anchor);
    });
  } else {
    group.anchorShapes.forEach((a) => {
      a.show();
      a.toFront();
    });
  }
  graph.paint();
};

Item.prototype.hideAnchor = function (graph) {
  if (graph.get("onDragEdge") === true) {
    return;
  }

  if (!!this.anchorDebounceTimer) {
    return;
  } else {
    this.anchorDebounceTimer = setTimeout(() => {
      try {
        if (this.getType() !== "node") {
          return;
        }
        const group = this.getContainer();
        if (!group.anchorShapes) {
          return;
        } else {
          group.anchorShapes.forEach((a) => a.hide());
        }
        this.anchorDebounceTimer = null;
        graph.paint();
      } catch (e) {}
    }, 100);
  }
};

Item.prototype.clearAnchor = function () {
  try {
    const group = this.getContainer();
    if (!!group.anchorShapes && group.anchorShapes.length > 0) {
      group.anchorShapes.forEach((i) => i.remove());
    }
  } catch (e) {
    // console.error(e)
  }
};

export function createAnchor(index, style, group) {
  const anchorContainer = group.addGroup();
  const anchor = new Item({
    type: "anchor",
    group: anchorContainer,
    capture: false,
    index,
    isActived: false,
    model: {
      style: {
        ...style,
        ...GraphStyle.anchorStyle,
        cursor: editorStyle.cursor.hoverEffectiveAnchor,
      },
    },
  });
  anchor.index = index;
  anchor.isAnchor = true;
  anchor.toFront();
  let hotpot;
  anchor.hideHotpot = function () {
    hotpot.remove();
  };
  anchor.showHotpot = function () {
    hotpot = anchorContainer.addShape("marker", {
      attrs: {
        ...style,
        ...GraphStyle.anchorHotsoptStyle,
      },
    });
    hotpot.toFront();
    anchor.getKeyShape().toFront();
  };
  anchor.setActived = function () {
    anchor.update({ style: { ...GraphStyle.anchorPointHoverStyle } });
  };
  anchor.clearActived = function () {
    anchor.update({ style: { ...GraphStyle.anchorStyle } });
  };
  anchor.setHotspotActived = function (act) {
    hotpot && (act ? hotpot.attr(GraphStyle.anchorHotsoptActivedStyle) : hotpot.attr(GraphStyle.anchorHotsoptStyle));
  };
  return anchorContainer;
}

export function registerAnchor(G6) {
  G6.Shape.registerFactory("anchor", {
    defaultShapeType: "marker",
  });
  G6.Shape.registerAnchor(
    "single-anchor",
    G6.Util.mix({}, SingleShapeMixin, {
      itemType: "anchor",

      drawShape(cfg, group) {
        const shapeType = this.shapeType;
        const style = this.getShapeStyle(cfg);
        const shape = group.addShape(shapeType, {
          attrs: style,
        });
        return shape;
      },

      setState(name, value, item) {
        if (name === "active-anchor") {
          if (value) {
            this.update({ style: { ...GraphStyle.anchorPointHoverStyle } }, item);
          } else {
            this.update({ style: { ...GraphStyle.anchorStyle } }, item);
          }
        }
      },
    })
  );
  G6.Shape.registerAnchor("marker", { shapeType: "marker" }, "single-anchor");
}
